package uk.ac.open.kmi.dyniqx.repositories;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.lucene.document.Field;
import org.directwebremoting.WebContext;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;

import uk.ac.open.kmi.dyniqx.storages.Storage;

public class PubMedThread extends Thread {
	
	public String queryString;
	public String queryKey;
	public String webEnv;
	public int count;

	public Storage storage;
	public WebContext wctx;
	
	public volatile boolean stop = false;
	
	public Logger logger = Logger.getLogger("uk.ac.open.kmi.dyniqx.repositories.PubMedThread");
	
	public PubMedThread(Storage storage, WebContext wctx, String queryString, String queryKey, String webEnv, int count) {
		
		this.setStorage(storage);
		this.setWctx(wctx);
		this.setQueryString(queryString);
		this.setQueryKey(queryKey);
		this.setWebEnv(webEnv);
		this.setCount(count);
		
	}
	
	@SuppressWarnings("unchecked")
	public void run() {
		
		this.logger.debug("Thread started.");
		
		SAXBuilder parser = new SAXBuilder();
		String searchUrl = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&retmode=xml";
		if (this.count > 100) this.count = 100;
		int retstart = 0;
		int retmax = 20;
		int temp_count = 0;
		Document doc;
		
		/* Open University proxy Settings */
		  
		System.getProperties().put( "proxySet", "true" );
		System.getProperties().put( "proxyHost", "wwwcache" );
		System.getProperties().put( "proxyPort", "80" );
		System.setProperty("java.net.useSystemProxies","true");
				
		try {
			
			while ((retstart <= (this.count - retmax)) && !stop) {
				
				doc = parser.build(searchUrl + "&webenv=" + this.getWebEnv() + "&query_key=" + this.getQueryKey() + "&retmax=" + retmax + "&retstart=" + retstart);
								
				List<Element> list = (List<Element>) XPath.newInstance("/PubmedArticleSet/PubmedArticle").selectNodes(doc);
			    Iterator iterator = list.iterator();
			    
			    org.apache.lucene.document.Document result = null;
			    ArrayList<org.apache.lucene.document.Document> documentArray = new ArrayList<org.apache.lucene.document.Document>();
			    
			    while (iterator.hasNext()) {
			        Element el = (Element) iterator.next();
			        
			        String id = XPath.newInstance("MedlineCitation/PMID").valueOf(el);
			        String title = XPath.newInstance("MedlineCitation/Article/ArticleTitle").valueOf(el);
			        String description = XPath.newInstance("MedlineCitation/Article/Abstract/AbstractText").valueOf(el);
			        
			        String link = "http://www.ncbi.nlm.nih.gov/sites/entrez?Db=pubmed&Cmd=ShowDetailView&TermToSearch=" + id;
			        String internal = "http://www.ncbi.nlm.nih.gov/sites/entrez?Db=pubmed&Cmd=ShowDetailView&TermToSearch=" + id;
			        
			        String year = XPath.newInstance("MedlineCitation/DateCreated/Year").valueOf(el);
			        String month = XPath.newInstance("MedlineCitation/DateCreated/Month").valueOf(el);
			        String day = XPath.newInstance("MedlineCitation/DateCreated/Day").valueOf(el);
			        		        
			        String journal = XPath.newInstance("MedlineCitation/MedlineJournalInfo/MedlineTA").valueOf(el);
			        
			        journal = journal.length() > 0 ? journal : "n/a";
			        
			        result = new org.apache.lucene.document.Document();

			        result.add(new Field("source", "PbM", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("type", "text", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("id", id, Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("query", queryString, Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("rank", Integer.toString(++temp_count), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        
			        result.add(new Field("link", link, Field.Store.YES, Field.Index.TOKENIZED));
			        result.add(new Field("internal", internal, Field.Store.YES, Field.Index.TOKENIZED));
			        result.add(new Field("title", title, Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.YES));
			        result.add(new Field("description", description, Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.YES));
			        
			        String date = year + (month.length() > 0 ? "/" + month : "") + (day.length() > 0 ? "/" + day : ""); 
			        
			        result.add(new Field("date", date, Field.Store.YES, Field.Index.UN_TOKENIZED));
			        
			        XPath foo = XPath.newInstance("MedlineCitation/Article/AuthorList/Author");
			        
			        List<Element> authList = (List<Element>) foo.selectNodes(el);
			        Iterator authIterator = authList.iterator();
			        String authors = "";
			        
			        while (authIterator.hasNext()) {
			        	
				        Element authElement = (Element) authIterator.next();
				        
				        String lastname = XPath.newInstance("LastName").valueOf(authElement);
				        String initials = XPath.newInstance("Initials").valueOf(authElement);
				        
				        authors += lastname + " " + initials + ", ";

			        }
			        
			        authors = authors.length() != 0 ? authors.substring(0, authors.length()-2) : "n/a";
			        
			        result.add(new Field("authors", authors, Field.Store.YES, Field.Index.TOKENIZED));
			        result.add(new Field("journal", journal, Field.Store.YES, Field.Index.UN_TOKENIZED));

			        result.add(new Field("summary", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("width", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("height", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("fileSize", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("fileFormat", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("thumbUrl", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("thumbWidth", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("thumbHeight", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        
			        result.setBoost(100 / temp_count);
			        
			        documentArray.add(result);
			    }
			    
			    this.storage.performIOAction(Storage.WRITE_ACTION, documentArray);
			    this.storage.updateGrid();

			    retstart += retmax;
			}
		    
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}		
		
		if (this.stop) {
			this.logger.debug("Thread killed.");
            return;
        }
		
		this.logger.debug("Thread ended.");
    }
	
	public void setQueryString(String queryString) {
		this.queryString = queryString;
	}
	
	public String getQueryString() {
		return this.queryString;
	}
	
	public void setQueryKey(String queryKey) {
		this.queryKey = queryKey;
	}
	
	public String getQueryKey() {
		return this.queryKey;
	}
	
	public void setWebEnv(String webEnv) {
		this.webEnv = webEnv;
	}
	
	public String getWebEnv() {
		return this.webEnv;
	}

	public void setCount(int count) {
		this.count = count;
	}
	
	public int getCount() {
		return this.count;
	}
	
	public void setStorage(Storage storage) {
		this.storage = storage;
	}	
	
	public Storage getStorage() {
		return this.storage;
	}

	public WebContext getWctx() {
		return wctx;
	}

	public void setWctx(WebContext wctx) {
		this.wctx = wctx;
	}
}
